//
//  ImagePicker.swift
//  App_Common
//
//  Created by 蒋晨成 on 2022/2/10.
//

import Photos
import Service
import UICore
import UIKit

public protocol ImagePickerDelegate: AnyObject {
    func didSelect(image: UIImage?)
}

public class ImagePicker: NSObject {
    private lazy var pickerController: UIImagePickerController = {
        let pickerController = UIImagePickerController()
        pickerController.delegate = self
        pickerController.allowsEditing = allowEditing
        pickerController.mediaTypes = ["public.image"]
        return pickerController
    }()

    private weak var presentationController: UIViewController?
    private weak var delegate: ImagePickerDelegate?

    private var allowEditing: Bool

    public init(presentationController: UIViewController, allowEditing: Bool = true, delegate: ImagePickerDelegate) {
        self.allowEditing = allowEditing
        self.presentationController = presentationController
        self.delegate = delegate
        super.init()
    }
}

extension ImagePicker {
    public enum PhotoLibraryAuthorizationStatus {
        case denied
        case authorized
        case limited

        static func applyPrivacy(complete: @escaping (_ status: PhotoLibraryAuthorizationStatus) -> Void) {
            if #available(iOS 14, *) {
                PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
                    DispatchQueue.main.async {
                        switch status {
                        case .limited:
                            complete(.limited)
                        case .authorized:
                            complete(.authorized)
                        default:
                            complete(.denied)
                        }
                    }
                }
            } else {
                PHPhotoLibrary.requestAuthorization { status in
                    DispatchQueue.main.async {
                        switch status {
                        case .authorized:
                            complete(.authorized)
                        default:
                            complete(.denied)
                        }
                    }
                }
            }
        }
    }

    enum CameraAuthorizationStatus {
        static func applyPrivacy(complete: @escaping (_ authorized: Bool) -> Void) {
            AVCaptureDevice.requestAccess(for: .video) { granted in
                DispatchQueue.main.async {
                    complete(granted)
                }
            }
        }
    }
}

public extension ImagePicker {
    static func alertChoose(from: UIViewController, complete: @escaping (_ status: UIImagePickerController.SourceType) -> Void) {
        let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            let action = UIAlertAction(title: CommonModular.localizedString(key: "Alert.Camera.Button.Title"), style: .default) { _ in
                complete(.camera)
            }
            alertController.addAction(action)
        }

        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
            let action = UIAlertAction(title: CommonModular.localizedString(key: "Alert.PhotoLibrary.Button.Title"), style: .default) { _ in
                complete(.photoLibrary)
            }
            alertController.addAction(action)
        }

        alertController.addAction(UIAlertAction(title: CommonModular.localizedString(key: "Alert.Cancel.Button.Title"), style: .cancel, handler: nil))
        from.present(alertController, animated: true)
    }
}

public extension ImagePicker {
    func showPhotoLibrary(customHandleStatus handle: @escaping (_ status: ImagePicker.PhotoLibraryAuthorizationStatus) -> Bool) {
        PhotoLibraryAuthorizationStatus.applyPrivacy { [weak self] status in
            guard let self = self else { return }
            if handle(status) {
                return
            }
            if status == .denied {
                let authViewController = ImageAuthorizationViewController(type: .photo)
                self.presentationController?.present(authViewController, animated: true)
                return
            }
            self.pickerController.sourceType = .photoLibrary
            self.presentationController?.present(self.pickerController, animated: true)
        }
    }

    func showCamera(customHandleStatus handle: @escaping (_ authorized: Bool) -> Bool) {
        CameraAuthorizationStatus.applyPrivacy { [weak self] authorized in
            guard let self = self else { return }
            if handle(authorized) {
                return
            }
            if !authorized {
                let authViewController = ImageAuthorizationViewController(type: .camera)
                self.presentationController?.present(authViewController, animated: true)
                return
            }
            self.pickerController.sourceType = .camera
            self.presentationController?.present(self.pickerController, animated: true)
        }
    }
}

extension ImagePicker: UIImagePickerControllerDelegate {
    private func pickerController(_ controller: UIImagePickerController, didSelect image: UIImage?) {
        controller.dismiss(animated: true, completion: nil)
        delegate?.didSelect(image: image)
    }

    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        pickerController(picker, didSelect: nil)
    }

    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        let image = allowEditing.map(
            true: info[.editedImage] as? UIImage,
            false: info[.originalImage] as? UIImage
        )
        pickerController(picker, didSelect: image)
    }
}

extension ImagePicker: UINavigationControllerDelegate {}
